package controllers;

import play.*;
import play.mvc.*;
import play.mvc.Scope.RenderArgs;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;

import models.Agent;
import models.CIS;
import models.Candidat;
import models.EtatCandid;
import models.FMPA;
import models.Grade;
import models.Groupement;
import models.Intitule;
import models.MotifAnnulation;
import models.NivFor;
import models.OrdresPriorite;
import models.Resultat;
import models.Role;
import models.Stage;
import models.Statut;
import models.Fonction;
import models.Uv;

@With(Secure.class)
public class Candidats extends CRUD { 

	/**
	 * Instancie des variables de session(session.put())
	 * Met ces variables dans des variables de rendu(render.args())
	 */
	@Before
	static void setConnectedUser() {
		if(Security.isConnected()) {
			if(!session.contains("agent_fullname")){
				Agent agent = Agent.find("nomUtilisateur", Security.connected()).first();
				Fonction gestFonct=Fonction.find("id_fonction like ?", "FONCT").first();
				Fonction gestTer=Fonction.find("id_fonction like ?", "TERRI").first();
				Fonction admin=Fonction.find("id_fonction like ?", "ADM").first();
				Fonction chef_CIS=Fonction.find("id_fonction like ?", "RCIS").first();
				Fonction formateur=Fonction.find("id_fonction like ?", "FOR").first();
				List<CIS> centres=CIS.find("responsable.id like ?", agent.id).fetch();
				boolean resp=!centres.isEmpty();
				/*
				 * Compte le nombre d'autorisation en attente pour les CIS où l'agent est responsable
				 * et l'ajoute à une variable de session et de rendu.
				 */
				List<Candidat> listeCandidats=new ArrayList<Candidat>();
				if(agent.fonction.contains(chef_CIS) || resp){
					Iterator<CIS> i=centres.iterator();
					while(i.hasNext()){
						List<Candidat> cand=Candidat.find("agent.cis.id like ? and etatCandid.id_etatcandid like ?", i.next().id, "AAUT").fetch();
						listeCandidats.addAll(cand);
					}
					session.put("nb_demande_auto", listeCandidats.size());
					renderArgs.put("nb_demande_auto", Integer.parseInt(session.get("nb_demande_auto")));
				}
				/*
				 * Compte le nombre de validations et d'annulations en attente et l'ajoute à une variable de session et de rendu.
				 */
				if(agent.fonction.contains(admin) || agent.fonction.contains(gestFonct)){
					long nbValidAdmin=Candidat.count("etatCandid.id_etatcandid like ? and demandeAnnulation is not true", "AVAL");
					long nbAnnulAdmin=Candidat.count("demandeAnnulation is true");
					session.put("nb_demande_valid_admin", nbValidAdmin);
					renderArgs.put("nb_demande_valid_admin", Integer.parseInt(session.get("nb_demande_valid_admin")));
					session.put("nb_demande_annul_admin", nbAnnulAdmin);
					renderArgs.put("nb_demande_annul_admin", Integer.parseInt(session.get("nb_demande_annul_admin")));
				}
				/*
				 * Compte le nombre de validations et d'annulations en attente pour le groupement dont l'agent est responsable
				 * et l'ajoute à une variable de session et de rendu.
				 */
				if(agent.fonction.contains(gestTer)){
					long nbValidTerri=Candidat.count("etatCandid.id_etatcandid like ? and stage.structure.responsable like ? and demandeAnnulation is not true", "AVAL", agent);
					long nbAnnulTerri=Candidat.count("demandeAnnulation is true and stage.structure.responsable.id like ? and etatCandid.id_etatcandid not like ? or etatCandid.nom not like ?", agent.id, "ANN", "REF");
					session.put("nb_demande_valid_terri", nbValidTerri);
					renderArgs.put("nb_demande_valid_terri", Integer.parseInt(session.get("nb_demande_valid_terri")));
					session.put("nb_demande_annul_terri", nbAnnulTerri);
					renderArgs.put("nb_demande_annul_terri", Integer.parseInt(session.get("nb_demande_annul_terri")));
				}

				/*
				 * Création des variables de session
				 */

				/*
				 * groupementResp_id représente l'id du groupement de l'agent si celui-ci est le responsable
				 * Sinon l'id du groupement auquel il appartient s'il possède la fonction gestionnaireTerritorial
				 */
				Groupement gpmt=Groupement.find("responsable like ?", agent).first();
				if(gpmt!=null){
					session.put("groupementResp_id", gpmt.id);
				}
				else if(agent.fonction.contains(gestTer)){
					session.put("groupementResp_id", agent.cis.groupement.id);
				}

				int aujourdhui=Calendar.getInstance().get(Calendar.YEAR);
				session.put("nomUtilisateur", agent.nomUtilisateur);
				session.put("anneeEnCours", aujourdhui);
				session.put("agent_id", agent.id);
				session.put("agent_niv", agent.niv.niv);
				session.put("agent_cis", agent.cis);
				session.put("agent_grpt", agent.cis.groupement);
				session.put("chef_CIS", agent.fonction.contains(chef_CIS));
				session.put("agent_email", agent.email);
				session.put("agent_fullname", agent.fullname());
				session.put("agent_responsable", resp);
				session.put("agent_grade", agent.grade.toString());
				session.put("gestionnaireFonct", (agent.fonction.contains(gestFonct)));
				session.put("gestionnaireTerri", agent.fonction.contains(gestTer));
				session.put("formateur", agent.fonction.contains(formateur));
				session.put("admin", agent.fonction.contains(admin));
				session.put("CISService", agent.cis.nom);
				/*
				 * Compte le nombre de validations en attente pour les fmpa et l'ajoute à une variable de session et de rendu.
				 */
				if(agent.fonction.contains(admin) || agent.fonction.contains(gestFonct)){
					long nbValidAdmin=FMPA.count("etat.nom like ?", "Attente de validation");
					session.put("nb_valid_fmpa", nbValidAdmin);
					renderArgs.put("nb_valid_fmpa", Integer.parseInt(session.get("nb_valid_fmpa")));
				}else if(agent.fonction.contains(gestTer)){
					long nbValidTerri=FMPA.count("etat.nom like ? and cis.groupement.nom like ?", "Attente de validation", session.get("agent_grpt"));
					session.put("nb_valid_fmpa", nbValidTerri);
					renderArgs.put("nb_valid_fmpa", Integer.parseInt(session.get("nb_valid_fmpa")));
				}else if(agent.fonction.contains(chef_CIS) || resp){
					long nbValidCis=FMPA.count("etat.nom like ? and cis.nom like ?", "Attente de validation", session.get("CISService"));
					session.put("nb_valid_fmpa", nbValidCis);
					renderArgs.put("nb_valid_fmpa", Integer.parseInt(session.get("nb_valid_fmpa")));
				}
				System.out.println(session.get("nb_valid_fmpa"));
				/*
				 * Création des variables de rendu
				 */
				if(session.contains("groupementResp_id")){
					renderArgs.put("groupementResp_id", Long.parseLong(session.get("groupementResp_id")));
				}
				renderArgs.put("anneeEnCours", Integer.parseInt(session.get("anneeEnCours")));
				renderArgs.put("CISService", session.get("CISService"));
				renderArgs.put("agent_niv", Integer.parseInt(session.get("agent_niv")));
				renderArgs.put("agent_grpt", session.get("agent_grpt"));
				renderArgs.put("chef_CIS", session.get("chef_CIS").equals("true"));
				renderArgs.put("admin", session.get("admin").equals("true"));
				renderArgs.put("formateur", session.get("formateur").equals("true"));
				renderArgs.put("agent_email", session.get("agent_email"));
				renderArgs.put("agent_fullname", session.get("agent_fullname"));
				renderArgs.put("agent_responsable", session.get("agent_responsable").equals("true"));
				renderArgs.put("agent_grade", session.get("agent_grade"));
				renderArgs.put("gestionnaireFonct", session.get("gestionnaireFonct").equals("true"));
				renderArgs.put("gestionnaireTerri", session.get("gestionnaireTerri").equals("true"));
				if(agent.niv.id != 0){
					session.put("agent_for", agent.niv);
					renderArgs.put("agent_for", session.get("agent_for"));
				}
				Calendar c=Calendar.getInstance();
				renderArgs.put("Annee", c.get(Calendar.YEAR));
			}
			else{
				/*
				 * Création des variables de rendu si les variables de session existent
				 */
				if(session.contains("nb_demande_valid_terri") || session.contains("nb_demande_annul_terri")){
					renderArgs.put("nb_demande_valid_terri", Integer.parseInt(session.get("nb_demande_valid_terri")));
					renderArgs.put("nb_demande_annul_terri", Integer.parseInt(session.get("nb_demande_annul_terri")));
				}
				if(session.contains("nb_demande_auto")){
					renderArgs.put("nb_demande_auto", Integer.parseInt(session.get("nb_demande_auto")));
				}
				if(session.contains("nb_demande_valid_admin") || session.contains("nb_demande_annul_admin")){
					renderArgs.put("nb_demande_valid_admin", Integer.parseInt(session.get("nb_demande_valid_admin")));
					renderArgs.put("nb_demande_annul_admin", Integer.parseInt(session.get("nb_demande_annul_admin")));
				}
				if(session.contains("nb_demande_auto")){
					renderArgs.put("nb_demande_auto", Integer.parseInt(session.get("nb_demande_auto")));
				}
				renderArgs.put("anneeEnCours", Integer.parseInt(session.get("anneeEnCours")));
				renderArgs.put("CISService", session.get("CISService"));
				renderArgs.put("agent_niv", Integer.parseInt(session.get("agent_niv")));
				renderArgs.put("agent_grpt", session.get("agent_grpt"));
				renderArgs.put("chef_CIS", session.get("chef_CIS").equals("true"));
				renderArgs.put("admin", session.get("admin").equals("true"));
				renderArgs.put("formateur", session.get("formateur").equals("true"));
				renderArgs.put("agent_email", session.get("agent_email"));
				renderArgs.put("agent_fullname", session.get("agent_fullname"));
				renderArgs.put("agent_responsable", session.get("agent_responsable").equals("true"));
				renderArgs.put("agent_grade", session.get("agent_grade"));
				renderArgs.put("gestionnaireFonct", session.get("gestionnaireFonct").equals("true"));
				renderArgs.put("gestionnaireTerri", session.get("gestionnaireTerri").equals("true"));
				renderArgs.put("agent_for", session.get("agent_for"));
				if(session.contains("nb_valid_fmpa")){
					renderArgs.put("nb_valid_fmpa", Integer.parseInt(session.get("nb_valid_fmpa")));
				}
				if(session.contains("groupementResp_id")){
					renderArgs.put("groupementResp_id", Long.parseLong(session.get("groupementResp_id")));
				}
				Calendar c=Calendar.getInstance();
				renderArgs.put("Annee", c.get(Calendar.YEAR));
			}
		}
	}

	/**
	 * Affiche les candidatures de l'utilisateur connecté
	 */
	public static void candidatures(){
		List<Candidat> candidatures=Candidat.find("agent.id like ? order by agent.nom", Long.decode(session.get("agent_id"))).fetch();
		List<Candidat>	attente=new ArrayList<Candidat>();
		List<Candidat>	refus=new ArrayList<Candidat>();
		List<Candidat>	valide=new ArrayList<Candidat>();
		List<Candidat>	annulee=new ArrayList<Candidat>();
		Iterator<Candidat> it=candidatures.iterator();
		while(it.hasNext()){
			Candidat cand=it.next();
			if(cand.etatCandid.id_etatcandid.equals("VAL")){
				valide.add(cand);
			}
			else if(cand.etatCandid.id_etatcandid.equals("REF") || cand.etatCandid.id_etatcandid.equals("NAUT")){
				refus.add(cand);
			}
			else if(cand.etatCandid.id_etatcandid.equals("ANN")){
				annulee.add(cand);
			}
			else{
				attente.add(cand);
			}
		}
		render(attente, refus, valide, annulee);
	} 

	/**
	 * Affiche les candidatures en attentes de l'utilisateur connecté
	 */
	public static void candidaturesAttente(){
		List<Candidat> candidatures=Candidat.find("agent.id like ? order by agent.nom", Long.decode(session.get("agent_id"))).fetch();
		List<Candidat>	attente=new ArrayList<Candidat>();
		Iterator<Candidat> it=candidatures.iterator();
		while(it.hasNext()){
			Candidat cand=it.next();
			if(cand.etatCandid.id_etatcandid.equals("AAUT") || cand.etatCandid.id_etatcandid.equals("AVAL") || cand.etatCandid.id_etatcandid.equals("LA")){
				attente.add(cand);
			}
		}
		render("@candidatures", attente);
	} 


	/**
	 * Affiche les candidatures refusées de l'agent connecté
	 */
	public static void candidaturesRefusee(){
		List<Candidat> candidatures=Candidat.find("agent.id like ? order by agent.nom", Long.decode(session.get("agent_id"))).fetch();
		List<Candidat>	refus=new ArrayList<Candidat>();
		Iterator<Candidat> it=candidatures.iterator();
		while(it.hasNext()){
			Candidat cand=it.next();
			if(cand.etatCandid.id_etatcandid.equals("REF") || cand.etatCandid.id_etatcandid.equals("NAUT")){
				refus.add(cand);
			}
		}
		render("@candidatures", refus);
	} 

	/**
	 * Affiche les candidatures validées de l'agent connecté
	 */
	public static void candidaturesValidee(){
		List<Candidat> candidatures=Candidat.find("agent.id like ? order by agent.nom", Long.decode(session.get("agent_id"))).fetch();
		List<Candidat>	valide=new ArrayList<Candidat>();
		Iterator<Candidat> it=candidatures.iterator();
		while(it.hasNext()){
			Candidat cand=it.next();
			if(cand.etatCandid.id_etatcandid.equals("VAL")){
				valide.add(cand);
			}
		}
		render("@candidatures", valide);
	} 

	/**
	 * Affiche les candidatures annulées de l'agent connecté
	 */
	public static void candidaturesAnnulee(){
		List<Candidat> candidatures=Candidat.find("agent.id like ? order by agent.nom", Long.decode(session.get("agent_id"))).fetch();
		List<Candidat>	annulee=new ArrayList<Candidat>();
		Iterator<Candidat> it=candidatures.iterator();
		while(it.hasNext()){
			Candidat cand=it.next();
			if(cand.etatCandid.id_etatcandid.equals("ANN")){
				annulee.add(cand);
			}
		}
		render("@candidatures", annulee);
	}

	/**
	 * Affiche le formulaire de demande d'annulation pour la candidature d'id id
	 * @param id
	 */
	public static void demandeAnnulation(long id){
		List<MotifAnnulation> motifs = MotifAnnulation.all().fetch();
		Candidat candidature = Candidat.findById(id);
		render(motifs, candidature);
	} 

	/**
	 * Sauve la demande d'annulation en mettant le motif d'annulation de la candidature d'id
	 * candidature_id au motif d'id motif_id
	 * @param candidature_id
	 * @param motif_id
	 */
	public static void demandeAnnulationSave(long candidature_id, long motif_id ){
		Candidat c = Candidat.findById(candidature_id);
		if(motif_id!=0){
			c.setMotifAnnulation((MotifAnnulation) MotifAnnulation.findById(motif_id));
			c.demandeAnnulation=true;
			c.save();
			flash.success("Votre demande d'annulation pour le stage "+c.stage+" a bien été prise en compte.");
			Candidats.candidatures();
		}
		else{
			flash.error("Veuillez choisir un motif");
			demandeAnnulation(candidature_id);
		}
	}

	/**
	 * Affiche la liste des candidatures en demande d'annulation du département
	 */
	public static void listDemandeAnnulation(){
		EtatCandid etat_annule=EtatCandid.find("id_etatcandid like ?", "ANN").first();
		//Si l'agent est administrateur ou gestionnaire fonctionnel, affiche la liste
		if(session.get("gestionnaireFonct").equals("true") || session.get("admin").equals("true")){
			List<Candidat> candidatures = Candidat.find("demandeAnnulation=true and etatCandid != ? and candidature_non_annuler = 0 order by agent.nom", etat_annule).fetch();
			render(candidatures);
		}
		else{
			render("@candidatures");
		}
	}

	/**
	 * Affiche la liste des candidatures en demande d'annulation du groupement pour lequel l'agent est responsable
	 */
	public static void listDemandeAnnulationTerri(){
		EtatCandid etat_annule=EtatCandid.find("id_etatcandid like ?", "ANN").first();
		//Si l'agent est gestionnaire territorial, affiche la liste
		if(session.get("gestionnaireTerri").equals("true") || Long.decode(session.get("groupementResp_id"))!=0){
			List<Candidat> candidatures = Candidat.find("demandeAnnulation=true and etatCandid != ? and candidature_non_annuler = 0 and agent.cis.groupement.id like ? order by agent.nom", etat_annule, Long.parseLong(session.get("groupementResp_id"))).fetch();
			render("@listDemandeAnnulation", candidatures);
		}
		else{
			render("@candidatures");
		}
	}

	/**
	 * Enregistre le formulaire de demande d'annulation du département
	 */
	public static void validationAnnulation(){
		EtatCandid etat_annule=EtatCandid.find("id_etatcandid like ?", "ANN").first();
		List<Candidat> candidatures = Candidat.find("motifAnnulation != null and etatCandid != ? ", etat_annule).fetch();
		Iterator<Candidat> i = candidatures.iterator();
		Candidat candidat;
		//parcours des candidatures de la structure d'id passe en paramètre
		while(i.hasNext()){
			candidat = i.next();
			if(params.get(""+candidat.id)!=null){
				//Si la demande d'annulation est validée, changer l'état de la candidature
				if(params.get(""+candidat.id).equals("oui")){
					candidat.setEtatCandid(etat_annule);
					candidat.candidature_non_annuler = false;
					//modifie les compteurs de demande d'annulation
					candidat.demandeAnnulation=false;
					candidat.save();
					if(session.contains("nb_demande_annul_admin")){
						long nbAnnulAdmin=Candidat.count("demandeAnnulation is true");
						session.put("nb_demande_annul_admin", nbAnnulAdmin);
					}
					if(session.contains("nb_demande_annul_terri")){
						long nbAnnulTerri=Candidat.count("demandeAnnulation is true and stage.structure.responsable.nomUtilisateur like ?", session.get("nomUtilisateur"));
						session.put("nb_demande_annul_terri", nbAnnulTerri);
					}
					//Modifie les compteurs de validation
					if(session.contains("nb_demande_valid_admin")){
						long nbValidAdmin=Candidat.count("etatCandid.id_etatcandid like ? and demandeAnnulation is not true", "AVAL");
						session.put("nb_demande_valid_admin", nbValidAdmin);
					}
					if(session.contains("nb_demande_valid_terri")){
						long nbValidTerri=Candidat.count("etatCandid.id_etatcandid like ? and stage.structure.responsable.nomUtilisateur like ? and demandeAnnulation is not true", "AVAL", session.get("nomUtilisateur"));
						session.put("nb_demande_valid_terri", nbValidTerri);
					}
				}
				//Si la demande n'est pas validée laisse la candidature dans son état actuel
				else if(params.get(""+candidat.id).equals("non")){
					candidat.candidature_non_annuler = true;
					//modifie les compteurs de demande d'annulation
					candidat.demandeAnnulation=false;
					candidat.save();
					if(session.contains("nb_demande_annul_admin")){
						long nbAnnulAdmin=Candidat.count("demandeAnnulation is true");
						System.out.println(Candidat.count("demandeAnnulation is true"));
						session.put("nb_demande_annul_admin", nbAnnulAdmin);
					}
					if(session.contains("nb_demande_annul_terri")){
						long nbAnnulTerri=Candidat.count("demandeAnnulation is true and stage.structure.responsable.nomUtilisateur like ?", session.get("nomUtilisateur"));
						session.put("nb_demande_annul_terri", nbAnnulTerri);
					}
					//Modifie les compteurs de validation
					if(session.contains("nb_demande_valid_admin")){
						long nbValidAdmin=Candidat.count("etatCandid.id_etatcandid like ? and demandeAnnulation is not true", "AVAL");
						session.put("nb_demande_valid_admin", nbValidAdmin);
					}
					if(session.contains("nb_demande_valid_terri")){
						long nbValidTerri=Candidat.count("etatCandid.id_etatcandid like ? and stage.structure.responsable.nomUtilisateur like ? and demandeAnnulation is not true", "AVAL", session.get("nomUtilisateur"));
						session.put("nb_demande_valid_terri", nbValidTerri);
					}
				}
			}
		}
		Candidats.listDemandeAnnulation();
	}

	/**
	 * Affiche les candidatures en attente de validation du département
	 */
	public static void validationCandidatures(){
		if(session.get("gestionnaireFonct").equals("true") || session.get("admin").equals("true")){
			List<OrdresPriorite> priorites=OrdresPriorite.findAll();
			List<Candidat> candidats=Candidat.find("etatCandid.id_etatcandid like ? and demandeAnnulation is not true order by id", "AVAL").fetch();
			render(candidats, priorites);
		}
		else{
			render("@accessDenied");
		}
	}

	/**
	 * Affiche les candidatures en attente de validation du groupement de l'agent
	 */
	public static void validationCandidaturesTerri(){
		if(session.get("gestionnaireTerri").equals("true") && session.contains("groupementResp_id")){
			List<OrdresPriorite> priorites=OrdresPriorite.findAll();
			List<Candidat> candidats=Candidat.find("etatCandid.id_etatcandid like ? and stage.structure.id like ? order by id", "AVAL", Long.decode(session.get("groupementResp_id"))).fetch();
			render("@validationCandidatures", candidats, priorites);
		}
		else{
			render("@accessDenied");
		}
	}

	/**
	 * Envoie du formulaire de validation de candidatures
	 */
	public static void envoieValidation(){
		//Récupération de la liste des candidatures en attente de validation
		List<Candidat> candidatures=new ArrayList<Candidat>();
		candidatures=Candidat.find("etatCandid.id_etatcandid like ?", "AVAL").fetch();
		Iterator<Candidat> itCandid=candidatures.iterator();
		EtatCandid etatOK=EtatCandid.find("id_etatcandid like ?", "VAL").first();
		EtatCandid etatNON=EtatCandid.find("id_etatcandid like ?", "REF").first();
		EtatCandid etatATTENTE=EtatCandid.find("id_etatcandid like ?", "LA").first();
		//Boucle sur les candidatures affichées et change l'état de la candidature en fonction de l'état du bouton radio
		while(itCandid.hasNext()){
			Candidat candidat=itCandid.next();
			//Si le bouton radio oui a été coché passe la candidature en état "Validée"
			if(params.get(""+candidat.id)!=null){
				if(params.get(""+candidat.id).equals("oui")){
					if(!candidat.candidPartielle && candidat.stage!=null && candidat.stage.effectifMax==candidat.stage.getEffectif() && candidat.role.id_role.equals("STAG")){
						flash.error("Le nombre maximum de stagiaires a été atteint");
					}
					else{
						//modifie les compteurs de demande d'annulation
						candidat.setEtatCandid(etatOK);
						candidat.save();
						if(session.contains("nb_demande_annul_admin")){
							long nbAnnulAdmin=Candidat.count("demandeAnnulation is true");
							session.put("nb_demande_annul_admin", nbAnnulAdmin);
						}
						if(session.contains("nb_demande_annul_terri")){
							long nbAnnulTerri=Candidat.count("demandeAnnulation is true and stage.structure.responsable.nomUtilisateur like ?", session.get("nomUtilisateur"));
							session.put("nb_demande_annul_terri", nbAnnulTerri);
						}
						//modifie les compteurs de demande de validation
						candidat.setEtatCandid(etatOK);
						candidat.save();
						if(session.contains("nb_demande_valid_admin")){
							long nbValidAdmin=Candidat.count("etatCandid.id_etatcandid like ? and demandeAnnulation is not true", "AVAL");
							session.put("nb_demande_valid_admin", nbValidAdmin);
						}
						if(session.contains("nb_demande_valid_terri")){
							long nbValidTerri=Candidat.count("etatCandid.id_etatcandid like ? and stage.structure.responsable.nomUtilisateur like ? and demandeAnnulation is not true", "AVAL", session.get("nomUtilisateur"));
							session.put("nb_demande_valid_terri", nbValidTerri);
						}
					}
				}
				//si la case Non a été coché, passage en état "non validée"
				else if(params.get(""+candidat.id).equals("non")){
					//modifie les compteurs de demande d'annulation
					candidat.setEtatCandid(etatNON);
					candidat.setMotifRefus(params.get("R"+candidat.id));
					candidat.save();
					if(session.contains("nb_demande_annul_admin")){
						long nbAnnulAdmin=Candidat.count("demandeAnnulation is true");
						session.put("nb_demande_annul_admin", nbAnnulAdmin);
					}
					if(session.contains("nb_demande_annul_terri")){
						long nbAnnulTerri=Candidat.count("demandeAnnulation is true and stage.structure.responsable.nomUtilisateur like ?", session.get("nomUtilisateur"));
						session.put("nb_demande_annul_terri", nbAnnulTerri);
					}
					//modifie les compteurs de demande de validation
					candidat.setEtatCandid(etatNON);
					candidat.setMotifRefus(params.get("R"+candidat.id));
					candidat.save();
					if(session.contains("nb_demande_valid_admin")){
						long nbValidAdmin=Candidat.count("etatCandid.id_etatcandid like ? and demandeAnnulation is not true", "AVAL");
						session.put("nb_demande_valid_admin", nbValidAdmin);
					}
					if(session.contains("nb_demande_valid_terri")){
						long nbValidTerri=Candidat.count("etatCandid.id_etatcandid like ? and stage.structure.responsable.nomUtilisateur like ? and demandeAnnulation is not true", "AVAL", session.get("nomUtilisateur"));
						session.put("nb_demande_valid_terri", nbValidTerri);
					}
				}

				//si la case Liste d'attente a été coché, passage en état "Liste d'attente"
				else if(params.get(""+candidat.id).equals("listeAttente")){
					//modifie les compteurs de demande d'annulation
					candidat.setEtatCandid(etatATTENTE);
					candidat.save();
					if(session.contains("nb_demande_annul_admin")){
						long nbAnnulAdmin=Candidat.count("demandeAnnulation is true");
						session.put("nb_demande_annul_admin", nbAnnulAdmin);
					}
					if(session.contains("nb_demande_annul_terri")){
						long nbAnnulTerri=Candidat.count("demandeAnnulation is true and stage.structure.responsable.nomUtilisateur like ?", session.get("nomUtilisateur"));
						session.put("nb_demande_annul_terri", nbAnnulTerri);
					}

					//modifie les compteurs de demande d'annulation
					candidat.save();
					if(session.contains("nb_demande_valid_admin")){
						long nbValidAdmin=Candidat.count("etatCandid.id_etatcandid like ? and demandeAnnulation is not true", "AVAL");
						session.put("nb_demande_valid_admin", nbValidAdmin);
					}
					if(session.contains("nb_demande_valid_terri")){
						long nbValidTerri=Candidat.count("etatCandid.id_etatcandid like ? and stage.structure.responsable.nomUtilisateur like ? and demandeAnnulation is not true", "AVAL", session.get("nomUtilisateur"));
						session.put("nb_demande_valid_terri", nbValidTerri);
					}
				}
			}
		}

		//si l'agent est admin ou gestionnaire fonctionnel, renvoi vers la validation de candidature admin
		if(session.get("admin").equals("true") || session.get("gestionnaireFonct").equals("true")){
			validationCandidatures();
		}
		//sinon renvoi vers la validation de candidature territorial
		else {
			validationCandidaturesTerri();
		}
	}

	/**
	 * Affiche la liste des stages du département pour la gestion
	 */
	public static void gestionCandidatures(){
		List<Stage> stages;
		if(session.get("gestionnaireFonct").equals("true") || session.get("admin").equals("true")){
			stages=Stage.findAll();
		}
		else{stages=Stage.find("organisateur.email = ? or gestionnaireAdmin.email = ?", session.get("agent_email"), session.get("agent_email")).fetch();}
		render(stages);
	}

	/**
	 * Affiche les stages du groupement de l'agent connecté pour la gestion
	 */
	public static void gestionCandidaturesTerri(){
		List<Stage> stages;
		if(session.get("gestionnaireTerri").equals("true")){
			stages=Stage.find("structure.id like ?", Long.parseLong(session.get("groupementResp_id"))).fetch();
		}
		else{stages=Stage.find("organisateur.email = ? or gestionnaireAdmin.email = ?", session.get("agent_email"), session.get("agent_email")).fetch();}
		render("@gestionCandidatures", stages);
	}

	/**
	 * Affiche la liste des candidatures à gérer pour le stage d'id stageId
	 * @param stageId
	 */
	public static void gerer(long stageId){
		Stage stage=Stage.findById(stageId);
		boolean isTerri=session.get("gestionnaireTerri").equals("true") && stage.structure.id==Long.decode(session.get("groupementResp_id"));
		//Vérification des droits de l'agent connecté
		//Si l'agent ne possède pas les droits suffisants il est redirigé vers la page accessDenied.html
		if (session.get("admin").equals("false") && session.get("gestionnaireFonct").equals("false") && !isTerri ){
			render("@accessDenied");
		}
		else{
			List<OrdresPriorite> priorites=OrdresPriorite.findAll();
			EtatCandid etat = EtatCandid.find("id_etatcandid like ?", "AAUT").first();
			List<Candidat> candidatures = Candidat.find("stage like ? and etatCandid not like ?", stage, etat).fetch();
			render(candidatures, stage, priorites);
		}
	}

	public static void gestionCandidatureSave(Long stageId){
		EtatCandid etatValide=EtatCandid.find("id_etatcandid like ?", "VAL").first();
		EtatCandid etatListeAttente=EtatCandid.find("id_etatcandid like ?", "LA").first();
		EtatCandid etatAnnule=EtatCandid.find("id_etatcandid like ?", "ANN").first();
		Stage stage = Stage.findById(stageId);
		List<Candidat> candidatures = Candidat.find("stage like ? ", stage).fetch();
		Iterator<Candidat> i = candidatures.iterator();
		Candidat candidat;
		//parcours des candidatures de la structure d'id passe en param
		while(i.hasNext()){
			candidat = (Candidat) i.next();
			if(params.get("validation_"+candidat.id)!=null){
				if(params.get("validation_"+candidat.id).equals("validee")){
					if(candidat.stage.effectifMax==candidat.stage.getEffectif() && candidat.role.id_role.equals("STAG")){
						flash.error("Le nombre maximum de stagiaires a été atteint");
					}
					else{
						if(candidat.demandeAnnulation){
							candidat.demandeAnnulation=false;
							if(session.contains("nb_demande_annul_admin")){
								long nbAnnulAdmin=Candidat.count("demandeAnnulation is true");
								session.put("nb_demande_annul_admin", nbAnnulAdmin);
							}
							if(session.contains("nb_demande_annul_terri")){
								long nbAnnulTerri=Candidat.count("demandeAnnulation is true and stage.structure.responsable.nomUtilisateur like ?", session.get("nomUtilisateur"));
								session.put("nb_demande_annul_terri", nbAnnulTerri);
							}
						}
						else if(candidat.etatCandid.id_etatcandid.equals("AVAL")){
							if(session.contains("nb_demande_valid_admin")){
								long nbValidAdmin=Candidat.count("etatCandid.id_etatcandid like ? and demandeAnnulation is not true", "AVAL");
								session.put("nb_demande_valid_admin", nbValidAdmin);
							}
							if(session.contains("nb_demande_valid_terri")){
								long nbValidTerri=Candidat.count("etatCandid.id_etatcandid like ? and stage.structure.responsable.nomUtilisateur like ? and demandeAnnulation is not true", "AVAL", session.get("nomUtilisateur"));
								session.put("nb_demande_valid_terri", nbValidTerri);
							}
						}
						candidat.setEtatCandid(etatValide);
						candidat.save();
					}
				}
				if(params.get("validation_"+candidat.id).equals("annulee")){
					if(candidat.demandeAnnulation){
						candidat.demandeAnnulation=false;
						if(session.contains("nb_demande_annul_admin")){
							long nbAnnulAdmin=Candidat.count("demandeAnnulation is true");
							session.put("nb_demande_annul_admin", nbAnnulAdmin);
						}
						if(session.contains("nb_demande_annul_terri")){
							long nbAnnulTerri=Candidat.count("demandeAnnulation is true and stage.structure.responsable.nomUtilisateur like ?", session.get("nomUtilisateur"));
							session.put("nb_demande_annul_terri", nbAnnulTerri);
						}
					}
					else if(candidat.etatCandid.id_etatcandid.equals("AVAL")){
						if(session.contains("nb_demande_valid_admin")){
							long nbValidAdmin=Candidat.count("etatCandid.id_etatcandid like ? and demandeAnnulation is not true", "AVAL");
							session.put("nb_demande_valid_admin", nbValidAdmin);
						}
						if(session.contains("nb_demande_valid_terri")){
							long nbValidTerri=Candidat.count("etatCandid.id_etatcandid like ? and stage.structure.responsable.nomUtilisateur like ? and demandeAnnulation is not true", "AVAL", session.get("nomUtilisateur"));
							session.put("nb_demande_valid_terri", nbValidTerri);
						}
					}
					candidat.setEtatCandid(etatAnnule);
					candidat.save();
				}
				if(params.get("validation_"+candidat.id).equals("listeAttente")){
					if(candidat.demandeAnnulation){
						candidat.demandeAnnulation=false;
						if(session.contains("nb_demande_annul_admin")){
							long nbAnnulAdmin=Candidat.count("demandeAnnulation is true");
							session.put("nb_demande_annul_admin", nbAnnulAdmin);
						}
						if(session.contains("nb_demande_annul_terri")){
							long nbAnnulTerri=Candidat.count("demandeAnnulation is true and stage.structure.responsable.nomUtilisateur like ?", session.get("nomUtilisateur"));
							session.put("nb_demande_annul_terri", nbAnnulTerri);
						}
					}
					else if(candidat.etatCandid.id_etatcandid.equals("AVAL")){
						if(session.contains("nb_demande_valid_admin")){
							long nbValidAdmin=Candidat.count("etatCandid.id_etatcandid like ? and demandeAnnulation is not true", "AVAL");
							session.put("nb_demande_valid_admin", nbValidAdmin);
						}
						if(session.contains("nb_demande_valid_terri")){
							long nbValidTerri=Candidat.count("etatCandid.id_etatcandid like ? and stage.structure.responsable.nomUtilisateur like ? and demandeAnnulation is not true", "AVAL", session.get("nomUtilisateur"));
							session.put("nb_demande_valid_terri", nbValidTerri);
						}
					}
					candidat.setEtatCandid(etatListeAttente);
					candidat.save();
				}
			}
		}
		flash.success("Modification effectuée");
		if(session.get("admin").equals("true") || session.get("gestionnaireFonct").equals("true")){
			Candidats.gestionCandidatures();
		}
		else {
			Candidats.gestionCandidaturesTerri();
		}
	}

	public static void ajouterCandidature(long stageId){
		List<CIS> cisServices=new ArrayList<CIS>();
		if(session.get("admin").equals("true") || session.get("gestionnaireFonct").equals("true")){
			cisServices = CIS.find("order by nom").fetch();
		}
		else if(session.get("gestionnaireTerri").equals("true")){
			cisServices=CIS.find("groupement.id like ? order by nom", Long.decode(session.get("groupementResp_id"))).fetch();
		}
		if(session.get("admin").equals("true") || session.get("gestionnaireFonct").equals("true") || session.get("gestionnaireTerri").equals("true")){
			List<Role> roles = Role.find("order by nom").fetch();
			List<Agent> agents = Agent.find("order by nom").fetch();
			Stage stage = Stage.findById(stageId);
			render(cisServices, roles, stage, agents);
		}
		else{
			render("@accessDenied");
		}
	}

	public static void ajouterCandidatureCis(long stageId){
		if(session.get("chef_CIS").equals("true") || session.get("agent_responsable").equals("true")){
			List<Role> roles = Role.find("order by nom").fetch();
			CIS cis=CIS.find("nom like ?", session.get("CISService")).first();
			List<Agent> agents = Agent.find("cis like ? order by nom", cis).fetch();
			Stage stage = Stage.findById(stageId);
			render(roles, stage, agents);
		}
		else{
			render("@accessDenied");
		}
	}

	public static void listStageAjouterCis(){
		List<Stage> stages; 
		Date aujourdhui = new Date();
		boolean isStage=true;
		//recuperation de la date du jour
		Calendar cal = Calendar.getInstance();
		//specification du format de sortie a utilise (celui reconnut par SQL)
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
		//permet de n'afficher que les stages non passés
		//utilisation de la methode find() de play.
		//on convertit la date actuelle fournit par Calendar en utilisant le SimpleDateFormat creer
		//specification de date, dateDeb doit etre superieur a la date actuel et non nul.
		stages=Stage.find("(dateDeb >= '"+sdf.format(cal.getTime())+"' or dateDeb is null) and (etat.id_etatstage not like ? or etat.id_etatstage not like ?)", "TER", "ANN" ).fetch();
		isStage=(stages.size()!=0);

		render(stages, aujourdhui, isStage);
	}

	public static void ajouterCandidatureSave(long stageId, long agent, boolean logement, String motivation, long role, String precisionDate, boolean candidPartielle){	
		if(agent!=0){
			Stage stage = Stage.findById(stageId);    
			List<Uv> uvs=stage.intitule.uVs;
			Iterator<Uv> i=uvs.iterator();
			Agent agentObj = Agent.findById(agent);
			Candidat c = new Candidat(agentObj, stage, motivation, role, null);
			EtatCandid etat = EtatCandid.find("id_etatcandid like ?", "VAL").first();
			c.setEtatCandid(etat);
			if(role != 0)
			{
				if(!stage.contientCandidat(c)){
					while(i.hasNext()){
						Uv uv=i.next();
						if(params.get(uv.nom)!=null){
							c.examenUv.add(uv);
						}
					}
					c.candidater(logement, role, precisionDate, candidPartielle);
					agentObj.save();
					stage.save();
					flash.success("La candidature a bien été enregistrée");
					ajouterCandidature(stageId);
				}
				else {
					Role roles = Role.findById(role);
					flash.error("Le candidat ne peut pas candidater en tant que "+roles.toString()+" pour ce stage");
					ajouterCandidature(stageId);
				}
			}
			else {
				flash.error("Vous devez choisir un rôle pour ce stage");
				ajouterCandidature(stageId);
			}
		}
		else{
			flash.error("Vous devez choisir un agent à ajouter");
			ajouterCandidature(stageId);
		}
	}


	public static void ajouterCandidatureSaveCis(Long stageId, Long agent, boolean logement, String motivation, long role, String precisionDate, boolean candidPartielle){	
		Stage stage = Stage.findById(stageId);    
		List<Uv> uvs=stage.intitule.uVs;
		Iterator<Uv> i=uvs.iterator();
		if(agent==0){
			flash.error("Indiquez un agent");
			Candidats.ajouterCandidatureCis(stageId);
		}
		Agent agentObj = Agent.findById(agent);
		Candidat c = new Candidat(agentObj, stage, motivation, role, null);
		EtatCandid etat = EtatCandid.find("id_etatcandid like ?", "AVAL").first();
		c.setEtatCandid(etat);
		if(role != 0)
		{
			if(!stage.contientCandidat(c)){
				while(i.hasNext()){
					Uv uv=i.next();
					if(params.get(uv.nom)!=null){
						c.examenUv.add(uv);
					}
				}
				c.candidater(logement, role, precisionDate, candidPartielle);
				agentObj.save();
				stage.save();
				flash.success("La candidature a bien été enregistrée");
				Candidats.ajouterCandidatureCis(stageId);
			}
			else {
				Role roles = Role.findById(role);
				flash.error("Le candidat ne peut pas candidater en tant que "+roles.toString()+" pour ce stage");
				Candidats.ajouterCandidatureCis(stageId);
			}
		}
		else {
			flash.error("Vous devez choisir un rôle pour ce stage");
			ajouterCandidatureCis(stageId);
		}
	}


	public static void candidaterNonPlanifie(){
		List<Intitule> intitules = Intitule.find("order by nom").fetch();
		List<Role> roles = Role.all().fetch();
		NivFor niv=NivFor.find("niv like ?",Integer.parseInt(session.get("agent_niv"))).first();
		render(intitules, roles, niv);
	}

	public static void candidaterNonPlanifieSave(long intitule, boolean logement, String motivation, long role, String precisionDate, boolean candidPartielle){

		Agent agent = Agent.findById(Long.decode(session.get("agent_id")));
		Intitule intituleObj= Intitule.findById(intitule);
		Candidat c = new Candidat(agent, null, motivation, role, intituleObj);
		if(!motivation.equals("") && !precisionDate.equals("") && role!=0){
			c.candidaterNonPlanifiee(logement, role, precisionDate, intitule, candidPartielle);
			agent.save();
			flash.success("Votre candidature a bien été enregistrée");
			candidaterNonPlanifie();
		}
		else if(role==0){
			flash.error("Veuillez choisir un rôle pour le stage.");
			List<Intitule> intitules = Intitule.all().fetch();
			List<Role> roles = Role.all().fetch();
			NivFor niv=NivFor.find("niv like ?",Integer.parseInt(session.get("agent_niv"))).first();
			render("@candidaterNonPlanifie", intitules, niv, roles );
		}
		else {
			flash.error("Vous devez remplir le champ motivation ou le champs détails.");
			List<Intitule> intitules = Intitule.all().fetch();
			List<Role> roles = Role.all().fetch();
			NivFor niv=NivFor.find("niv like ?",Integer.parseInt(session.get("agent_niv"))).first();
			render("@candidaterNonPlanifie", intitules, niv, roles );
		}
	}

	public static void changerPriorite(long id, long prioriteId){
		Candidat candidat=Candidat.findById(id);
		OrdresPriorite priorite=OrdresPriorite.findById(prioriteId);
		List<OrdresPriorite> priorites=OrdresPriorite.findAll();
		candidat.ordrePrioriteGrpmt=priorite;
		candidat.save();
		render(candidat, priorites);
	}

	public static void changerResultat(long id, long resultat){
		Candidat candidat=Candidat.findById(id);
		if(resultat!=0){
			candidat.resultat=Resultat.findById(resultat);
			candidat.save();
		}
		render(candidat);
	}

	public static void entrerResultat(long id){
		if (!session.get("admin").equals("true") && !session.get("gestionnaireFonct").equals("true")){
			render("@accessDenied");
		}
		else{
			Stage stage=Stage.findById(id);
			List<Candidat> candidatures=stage.candidatures;
			List<Resultat> resultats=Resultat.all().fetch();
			render(candidatures, stage, resultats);
		}
	}

	public static void afficherNonPlanifie(){
		List<Candidat> candidat=Candidat.find("intitule not null").fetch();
		render(candidat);
	}

	public static void detailCandid(long id){
		Candidat candidat=Candidat.findById(id);
		render(candidat);
	}
}